package com.example.service;

import com.example.common.enums.ResultCodeEnum;
import com.example.common.enums.RoleEnum;
import com.example.common.enums.SegmentEnum;
import com.example.common.enums.WeekEnum;
import com.example.entity.Account;
import com.example.entity.Choice;
import com.example.entity.Course;
import com.example.entity.Curriculum;
import com.example.entity.Student;
import com.example.entity.Teacher;
import com.example.exception.CustomException;
import com.example.mapper.ChoiceMapper;
import com.example.mapper.CourseMapper;
import com.example.utils.TokenUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 选课信息表业务处理
 **/
@Service
public class ChoiceService {

    @Resource
    private ChoiceMapper choiceMapper;
    @Resource
    private CourseMapper courseMapper;

    /**
     * 新增
     */
    public void add(Choice choice) {
        // 当前选的课
        Course course = courseMapper.selectById(choice.getCourseId());
        // 1. 先判断一下该门课选满了没有
        // 1) 我们可以在选课信息表里面查询该门课被选的次数（用这种方式）
        // 2) 这种方式大家自己去尝试：在课程信息表里面加个字段（已选人数），判断当前这门课的这个已选人数字段是否已经等于上课人数字段的值
        List<Choice> list = choiceMapper.selectByCourseId(choice.getCourseId());
        if (course.getNum().equals(list.size())) {
            throw new CustomException(ResultCodeEnum.COURSE_NUM_ERROR);
        }

        // 2. 判断该学生选的这么课的开课时间有没有和他之前选的课有冲突
        List<Choice> sList = choiceMapper.selectByStudentId(choice.getStudentId());
        for (Choice dbChoice : sList) {
            Course tmpCourse = courseMapper.selectById(dbChoice.getCourseId());
            if (course.getWeek().equals(tmpCourse.getWeek()) && course.getSegment().equals(tmpCourse.getSegment())) {
                throw new CustomException("-1", "您之前已经选过" + tmpCourse.getName() + ", 与该门课的上课时间冲突，请重新选择");
            }
        }

        choiceMapper.insert(choice);
    }

    /**
     * 删除
     */
    public void deleteById(Integer id) {
        choiceMapper.deleteById(id);
    }

    /**
     * 批量删除
     */
    public void deleteBatch(List<Integer> ids) {
        // 使用 Java 21 增强的 Stream API
        ids.forEach(choiceMapper::deleteById);
    }
    /**
     * 修改
     */
    public void updateById(Choice choice) {
        choiceMapper.updateById(choice);
    }

    /**
     * 根据ID查询
     */
    public Choice selectById(Integer id) {
        return choiceMapper.selectById(id);
    }

    /**
     * 查询所有
     * 添加权限控制：学生只能查看自己的选课记录，教师只能查看选了自己课程的记录
     */
    public List<Choice> selectAll(Choice choice) {
        List<Choice> list = choiceMapper.selectAll(choice);
        
        // 获取当前登录用户
        Account currentUser = TokenUtils.getCurrentUser();
        if (currentUser == null) {
            return list;
        }
        
        // 根据角色过滤选课数据
        return switch (currentUser.getRole()) {
            case "STUDENT" -> {
                // 学生只能看到自己的选课记录
                Student student = (Student) currentUser;
                yield list.stream()
                        .filter(c -> c.getStudentId().equals(student.getId()))
                        .collect(Collectors.toList());
            }
            case "TEACHER" -> {
                // 教师只能看到选了自己课程的记录
                Teacher teacher = (Teacher) currentUser;
                yield list.stream()
                        .filter(c -> c.getTeacherId().equals(teacher.getId()))
                        .collect(Collectors.toList());
            }
            default -> list; // 管理员可以看到所有选课记录
        };
    }

    /**
     * 分页查询
     * 添加权限控制：学生只能查看自己的选课记录，教师只能查看选了自己课程的记录
     */
    public PageInfo<Choice> selectPage(Choice choice, Integer pageNum, Integer pageSize) {
        // 获取当前登录用户
        Account currentUser = TokenUtils.getCurrentUser();
        if (currentUser != null) {
            switch (currentUser.getRole()) {
                case "STUDENT" -> {
                    // 学生只能看到自己的选课记录
                    Student student = (Student) currentUser;
                    choice.setStudentId(student.getId());
                }
                case "TEACHER" -> {
                    // 教师只能看到选了自己课程的记录
                    Teacher teacher = (Teacher) currentUser;
                    choice.setTeacherId(teacher.getId());
                }
                // 管理员不做限制
            }
        }
        
        PageHelper.startPage(pageNum, pageSize);
        List<Choice> list = choiceMapper.selectAll(choice);
        return PageInfo.of(list);
    }

    /**
     * 获取当前用户的课程表
     * 学生：显示自己选的课程
     * 教师：显示自己教授的课程
     * 使用 JDK 21 的 Stream API 和现代化编程方式
     */
    public List<Curriculum> getCurriculum() {
        Account currentUser = TokenUtils.getCurrentUser();
        if (currentUser == null) {
            return new ArrayList<>();
        }

        // 根据角色获取课程列表
        List<Course> courses = switch (currentUser.getRole()) {
            case "STUDENT" -> {
                // 学生：获取所有选课对应的课程
                List<Choice> choiceList = choiceMapper.selectByStudentId(currentUser.getId());
                yield choiceList.stream()
                        .map(choice -> courseMapper.selectById(choice.getCourseId()))
                        .filter(course -> course != null)
                        .toList();
            }
            case "TEACHER" -> {
                // 教师：获取自己教授的所有课程
                Teacher teacher = (Teacher) currentUser;
                Course queryCourse = new Course();
                queryCourse.setTeacherId(teacher.getId());
                yield courseMapper.selectAll(queryCourse);
            }
            default -> new ArrayList<>();
        };

        if (courses.isEmpty()) {
            return new ArrayList<>();
        }

        // 构建课程表
        List<Curriculum> curriculumList = new ArrayList<>();
        
        // 遍历所有时段
        for (SegmentEnum segment : SegmentEnum.values()) {
            Curriculum curriculum = new Curriculum();
            curriculum.setSegment(segment.segment);

            // 使用 JDK 21 的 switch 表达式填充每个星期的课程
            for (WeekEnum week : WeekEnum.values()) {
                Optional<Course> courseOpt = courses.stream()
                        .filter(course -> segment.segment.equals(course.getSegment()) 
                                && week.week.equals(course.getWeek()))
                        .findFirst();

                String courseName = courseOpt.map(Course::getName).orElse("");

                // 使用 switch 表达式设置对应星期的课程
                switch (week) {
                    case MONDAY -> curriculum.setMonday(courseName);
                    case TUESDAY -> curriculum.setTuesday(courseName);
                    case WEDNESDAY -> curriculum.setWednesday(courseName);
                    case THURSDAY -> curriculum.setThursday(courseName);
                    case FRIDAY -> curriculum.setFriday(courseName);
                    case SATURDAY -> curriculum.setSaturday(courseName);
                    case SUNDAY -> curriculum.setSunday(courseName);
                }
            }

            curriculumList.add(curriculum);
        }

        return curriculumList;
    }

}
